import { convertIpfsToHttp } from '../pages/Main/utils.ts';

import { getTokensMeta } from './walletsAPI.ts';

const BACKEND_URL = 'http://89.232.170.15:3000';

type FetchOptions = {
    url: string;
    options?: RequestInit;
    timeout?: number;
};

const fetchJSON = async ({ url, options }: {url: string; options?: RequestInit}) => {
    const response = await fetch(url, options);
    return await response.json();
};

export const fetchWithTimeout = async <T>({
    url, 
    options = {}, 
    timeout = 5000, 
}: FetchOptions): Promise<T> => {
    const controller = new AbortController();
    const signal = controller.signal;

    // Настройка таймаута для отмены запроса
    const timeoutId = setTimeout(() => controller.abort(), timeout);

    try {
        const response = await fetch(url, { ...options, signal });
        // Очистка таймаута при успешном завершении запроса
        clearTimeout(timeoutId);

        if (!response.ok) {
            throw new Error('Network response was not ok');
        }

        return  await response.json();
    } catch (error) {
        // Проверка, была ли ошибка вызвана абортированием
        if (error instanceof Error && error.name === 'AbortError') {
            throw new Error('Request was aborted due to timeout');
        }
        throw error;
    }
};

export const getTokenCollectionsByAccount = async (account: string) => {
    const collectionList: Record<string, Array<{contractAddress: string; type: string}>> = await fetchJSON({
        url: `https://test.siberium.net/api?module=account&action=tokenlist&address=${account}`,   
    });

    return collectionList.result.reduce((result: string[], currentValue) => {
        if (currentValue.type === 'ERC-721') {
            result.push(currentValue.contractAddress);
        }
        return result;
    }, []);
};

export const getNFTMetadata = async (url:string) => {
    return await fetchWithTimeout<{name: string, image: string}>({
        url: convertIpfsToHttp(url),
        timeout: 1000,
    });
};

export const getWalletsList = async () => {
    return await fetchJSON({
        url: `${BACKEND_URL}/wallet/wallets`,
    });
};

export const getTokensMetadataByWallet = async (address: string) => {
    const response = await fetchJSON({
        url: `${BACKEND_URL}/wallet?address=${address}`,
    });

    const tokensMeta = await getTokensMeta(Object.values(response[0].data).map(token => {
        const parsedToken = JSON.parse(token as string);
        return {
            tokenContract: parsedToken.tokenContract,
            tokenID: BigInt(parsedToken.tokenContract),
            tokenURI: parsedToken.tokenURI,
        };
    }));
    
    return {
        address,
        tokensMeta,
    };
};